package net.ib.mtalk.network.pipeline;

/*
 * Copyright 2009 Red Hat, Inc.
 *
 * Red Hat licenses this file to you under the Apache License, version 2.0
 * (the "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.TrustManagerFactorySpi;
import javax.net.ssl.X509TrustManager;

import net.ib.mtalk.util.MTalkLogWriter;

/**
 * Bogus {@link TrustManagerFactorySpi} which accepts any certificate
 * even if it is invalid.
 *
 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
 * @author <a href="http://gleamynode.net/">Trustin Lee</a>
 *
 * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
 */
public class SecureTrustManagerFactory extends TrustManagerFactorySpi {

	public static class MyTrustManager implements X509TrustManager {
		/* 
		 * The default X509TrustManager returned by SunX509.  We'll delegate 
		 * decisions to it, and fall back to the logic in this class if the 
		 * default X509TrustManager doesn't trust it. 
		 */  
		X509TrustManager x509TrustManager;

		public MyTrustManager() throws Exception {
			super();
			
			TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("X509");
			tmFactory.init((KeyStore)null);

			for (TrustManager trustManager : tmFactory.getTrustManagers()) {
				if (trustManager instanceof X509TrustManager) {
					x509TrustManager = (X509TrustManager) trustManager;
					return;
				}  
			}

			throw new Exception("SecureTrustManagerFactory.MyTrustManager(): Cannot initialize");
		}  

		public X509Certificate[] getAcceptedIssuers() {
			if (x509TrustManager == null)
				return null;
			return x509TrustManager.getAcceptedIssuers();
		}

		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			//x509TrustManager.checkClientTrusted(chain, authType);
			 throw new UnsupportedOperationException();
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			x509TrustManager.checkServerTrusted(chain, authType);
			MTalkLogWriter.d("SecureTrustManagerFactory.MyTrustManager.checkServerTrusted(): "+ chain[0].getIssuerDN().toString());
		}
	};

	private static MyTrustManager DUMMY_TRUST_MANAGER = null;
	static {
		try {
			if (DUMMY_TRUST_MANAGER == null) {
				DUMMY_TRUST_MANAGER = new MyTrustManager();
			}
		} catch(Exception e) {
			MTalkLogWriter.e(e);
		}
	}

	public static TrustManager[] getTrustManagers() {
		return new TrustManager[] {DUMMY_TRUST_MANAGER};
	}

	@Override
	protected TrustManager[] engineGetTrustManagers() {
		return getTrustManagers();
	}

	@Override
	protected void engineInit(KeyStore keystore) throws KeyStoreException {
		// Unused
	}

	@Override
	protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
	throws InvalidAlgorithmParameterException {
		// Unused
	}
}
